package com.quanyue.haircut.system.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.sign.Credentials;
import com.quanyue.auto.cache.core.CacheService;
import com.quanyue.haircut.domain.entity.FsConfig;
import com.quanyue.haircut.system.mapper.FsConfigMapper;
import com.quanyue.haircut.system.service.FsConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class FsConfigServiceImpl implements FsConfigService {

    private static final String FS_CONFIG = "FS_CONFIG";
    private static final String FS_CLIENT = "FS_CLIENT";
    @Autowired
    private FsConfigMapper configMapper;
    @Autowired
    private CacheService cacheService;

    @Override
    public FsConfig findByMerchant(Integer merchantNo) {
        return fsConfigMap().getOrDefault(merchantNo, new FsConfig());
    }

    @Override
    public void update(FsConfig config) {
        FsConfig exist = fsConfigMap().get(config.getMerchantNo());
        if (exist == null) {
            configMapper.insert(config);
        } else {
            config.setId(exist.getId());
            configMapper.update(config);
        }
        this.updateCache(config);
    }

    @Override
    public String getBucket(Integer merchantNo) {
        return fsConfigMap().getOrDefault(merchantNo, new FsConfig()).getBucket();
    }

    @Override
    public COSClient client(Integer merchantNo) {
        return clientMap().get(merchantNo);
    }

    @Override
    public String getDomainUrl(Integer merchantNo) {
        return fsConfigMap().getOrDefault(merchantNo, new FsConfig()).getDomainUrl();
    }

    private Map <Integer, FsConfig> fsConfigMap() {
        Type type = new TypeReference <Map <Integer, FsConfig>>() {
        }.getType();
        return cacheService.get(FS_CONFIG, type);
    }

    private Map <Integer, COSClient> clientMap() {
        Type type = new TypeReference <Map <Integer, COSClient>>() {
        }.getType();
        return cacheService.get(FS_CLIENT, type);
    }

    private void updateCache(FsConfig config) {
        fsConfigMap().put(config.getMerchantNo(), config);
        clientMap().put(config.getMerchantNo(), this.createClient(config));
    }

    private COSClient createClient(FsConfig config) {
        Credentials cred = new Credentials(config.getAppId().longValue(), config.getSecretId(), config.getSecretKey());
        ClientConfig clientConfig = new ClientConfig();
        clientConfig.setRegion(config.getRegion());
        return new COSClient(clientConfig, cred);
    }

    @PostConstruct
    private void init() {
        Map <Integer, FsConfig> configs = configMapper.findAll()
                .stream()
                .collect(Collectors.toMap(FsConfig::getMerchantNo, f -> f));
        cacheService.set(FS_CONFIG, configs);
        Map <Integer, COSClient> clientMap = new HashMap <>(configs.size());
        configs.forEach((merchantNo, fsConfig) -> clientMap.put(merchantNo, this.createClient(fsConfig)));
        cacheService.set(FS_CLIENT, clientMap);
    }
}
